package com.boot.project.module.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boot.project.core.enums.code.impl.commonCode.ResultCode;
import com.boot.project.core.enums.code.impl.systemCode.ResourceCode;
import com.boot.project.core.exception.CustomerException;
import com.boot.project.core.model.system.criteria.ResourceCriteria;
import com.boot.project.core.model.system.dto.ResourceSaveDto;
import com.boot.project.core.model.system.entity.Resource;
import com.boot.project.core.model.system.vo.ResourceVo;
import com.boot.project.module.system.mapper.ResourceMapper;
import com.boot.project.module.system.service.ResourceService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;

    /**
     * 分页条件查询
     *
     * @param criteria 查询条件
     * @return
     */
    @Override
    public Page<Resource> page(ResourceCriteria criteria) {
        // 1.封装查询对象
        QueryWrapper<Resource> wrapper = new QueryWrapper<>();
        if (StrUtil.isNotBlank(criteria.getName())) {
            wrapper.like("name", criteria.getName());
        }
        if (ObjectUtil.isNotNull(criteria.getType())) {
            wrapper.eq("type", criteria.getType());
        }
        if (StrUtil.isNotBlank(criteria.getPermission())) {
            wrapper.like("permission", criteria.getPermission());
        }
        wrapper.orderByDesc("update_time");
        // 2.进行查询
        Page<Resource> pageInfo = new Page<>(criteria.getPage(), criteria.getSize());
        resourceMapper.selectPage(pageInfo, wrapper);
        // 3.结果处理
        if (pageInfo.getTotal() == 0) {
            throw new CustomerException(ResultCode.RETURN_DATA_NOT_FOUND);
        }
        return pageInfo;
    }

    /**
     * 新增资源信息
     *
     * @param resourceSaveDto 资源信息
     */
    @Override
    public void add(ResourceSaveDto resourceSaveDto) {
        // 1.校验参数
        Resource dbResource = resourceMapper.findByName(resourceSaveDto.getName());
        if (dbResource != null) {
            throw new CustomerException(ResourceCode.EXISTS_RESOURCE_NAME);
        }
        // 2.封装数据
        Resource resource = new Resource(resourceSaveDto);
        // 3.进行保存
        int i = resourceMapper.insert(resource);
        // 4.对结果进行处理
        if (i != 1) {
            throw new CustomerException(ResultCode.INSERT_FAILURE);
        }
    }

    /**
     * 根据id查询资源信息
     *
     * @param id
     * @return
     */
    @Override
    public Resource findOne(Long id) {
        // 1.进行查询
        Resource dbResource = resourceMapper.selectById(id);
        // 2.对结果进行判断
        if (dbResource == null) {
            throw new CustomerException(ResultCode.RETURN_DATA_NOT_FOUND);
        }
        return dbResource;
    }

    /**
     * 更新资源信息
     *
     * @param resourceSaveDto 资源信息
     */
    @Override
    public void edit(ResourceSaveDto resourceSaveDto) {
        // 1.校验参数
        if (resourceSaveDto.getId() == null) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "更新时，资源id不能为空");
        }
        Resource dbResource = resourceMapper.selectById(resourceSaveDto.getId());
        if (dbResource == null) {
            throw new CustomerException(ResultCode.RETURN_DATA_NOT_FOUND, "更新时，没有找到需要更新的资源");
        }
        Resource tempResource = resourceMapper.findByName(resourceSaveDto.getName());
        if (tempResource != null && !tempResource.getId().equals(resourceSaveDto.getId())) {
            throw new CustomerException(ResourceCode.EXISTS_RESOURCE_NAME);
        }
        // 2.封装数据
        BeanUtils.copyProperties(resourceSaveDto, dbResource);
        // 3.进行保存
        int i = resourceMapper.updateById(dbResource);
        // 4.对结果进行处理
        if (i != 1) {
            throw new CustomerException(ResultCode.UPDATE_FAILURE);
        }
    }

    /**
     * 批量删除资源信息
     *
     * @param ids 资源id的集合
     */
    @Override
    public void delete(List<Long> ids) {
        // 1.参数校验
        if (CollectionUtil.isEmpty(ids)) {
            throw new CustomerException(ResultCode.HANDLE_DATA_NOT_EXISTED, "没有需要删除的资源信息");
        }
        // 如果它的下面有子资源，那么不给删
        for (Long id : ids) {
            List<Resource> list = resourceMapper.findByParentId(id);
            if (!CollectionUtils.isEmpty(list)) {
                throw new CustomerException(ResourceCode.EXISTS_CHILD, "id为" + id + "的资源下存在子资源，不能删除");
            }
        }
        // 2.进行删除
        int i = resourceMapper.deleteBatchIds(ids);
        // 3.对结果进行处理
        if (i != ids.size()) {
            throw new CustomerException(ResultCode.DELETE_FAILURE);
        }
    }

    /**
     * 查询所有的权限
     *
     * @return
     */
    @Override
    public List<ResourceVo> findAll() {
        List<Resource> list = resourceMapper.selectList(null);
        if (CollectionUtil.isEmpty(list)) {
            throw new CustomerException(ResultCode.RETURN_DATA_NOT_FOUND);
        }
        List<ResourceVo> voList = new ArrayList<>();
        for (Resource resource: list) {
            voList.add(new ResourceVo(resource));
        }
        return transferToTreeNodes(voList);
    }

    /**
     * 将List<Resource>转为树形结构
     * @param list 待处理的集合
     * @return
     */
    private List<ResourceVo> transferToTreeNodes(List<ResourceVo> list) {
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<ResourceVo> voList = new ArrayList<>();

        // 1.转为树形结构
        for (ResourceVo vo : list) {
            Long pid = vo.getParentId();
            // 处理根节点
            if (pid == 0) {
                voList.add(vo);
                continue;
            }
            // 处理非根节点
            for (ResourceVo parent : list) {
                Long id = parent.getId();
                if (id != null && id.equals(pid)) {//表示有子级结点，就给Children设置对象
                    if (null == parent.getChildren()) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(vo);
                }
            }
        }

        // 2.排序
        sortBySortAsc(voList);

        return voList;
    }

    /**
     * 根据sort排序
     * @param voList 需要排序的集合
     */
    private void sortBySortAsc(List<ResourceVo> voList) {
        if (!CollectionUtils.isEmpty(voList)) {
            voList.sort((o1, o2) -> {
                Integer sort1 = o1.getSort();
                Integer sort2 = o2.getSort();
                return sort1.compareTo(sort2);
            });
            for (ResourceVo item : voList) {
                if (!CollectionUtils.isEmpty(item.getChildren())) {
                    sortBySortAsc(item.getChildren());
                }
            }
        }
    }

    /**
     * 根据角色id查询资源id的集合
     *
     * @param roleId 角色id
     * @return
     */
    @Override
    public List<String> findIdsByRoleId(Long roleId) {
        List<Resource> resources = resourceMapper.findByRoleId(roleId);
        if (CollectionUtil.isEmpty(resources)) {
            throw new CustomerException(ResultCode.RETURN_DATA_NOT_FOUND);
        }
        return resources.stream().map(Resource::getId).map(String::valueOf).collect(Collectors.toList());
    }

    /**
     * 根据父id查询资源信息
     *
     * @param parentId 父id
     * @return
     */
    @Override
    public List<Resource> findByParentId(Long parentId) {
        List<Resource> resources = resourceMapper.findByParentId(parentId);
        if (CollectionUtil.isEmpty(resources)) {
            throw new CustomerException(ResultCode.RETURN_DATA_NOT_FOUND);
        }
        return resources;
    }
}
